///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_IMAGE_CMVIEW_H_
#define _BUOLA_IMAGE_CMVIEW_H_

#include <buola/image/cview.h>

namespace buola { namespace img {

template<typename tFmt,int vPixelAdvance=1>
class CMView : public CView<tFmt,vPixelAdvance>
{
    typedef CView<tFmt,vPixelAdvance> TBase;
public:
    typedef CMView<tFmt,vPixelAdvance> TView;
    typedef typename TBase::TValue TValue;
    typedef TValue* TPointer;
    typedef CPixelXIterator<TValue,tFmt,vPixelAdvance> TXIterator;
    typedef CPixelYIterator<TValue,tFmt> TYIterator;
    typedef typename TXIterator::TAccessor TAccessor;
    typedef CViewRow<TView> TRow;
    typedef CViewCol<TView> TCol;
    
    template<typename tF=tFmt,int pA=vPixelAdvance>
    struct MRebind
    {
        typedef CMView<tF,pA> type;
    };
    
public:
    CMView()
    {}

    CMView(TPointer pData,const CSize_i &pSize)
        :   TBase(pData,pSize)
    {}

    CMView(TPointer pData,const CSize_i &pSize,ptrdiff_t pStride)
        :   TBase(pData,pSize,pStride)
    {}

    CMView(const CMView &pRH)
        :   TBase((const TBase&)pRH)
    {}

    CMView(NRawBytes,uint8_t *pData,const CSize_i &pSize,ptrdiff_t pStride)
        :   TBase(nRawBytes,pData,pSize,pStride)
    {}
    
    explicit CMView(CAnyImage&);
   
    CMView &operator=(const CMView&)=default;

public:
    TPointer RawData(int x,int y) const    {    return TPointer(TBase::mData+TBase::mStride*y)+
                                                       TBase::cChannels*vPixelAdvance*x;    }
    TPointer RawData() const                            {   return TPointer(TBase::mData);          }
    
    TAccessor operator()(const CPoint_i &pP) const         {   return TAccessor(RawData(pP.x,pP.y));           }
    TAccessor operator()(int x,int y) const                 {   return TAccessor(RawData(x,y));                 }

    uint8_t *RawBytes() const                     {   return TBase::mData;                       }
    
    TXIterator XIterator(int x,int y) const       {   return TXIterator(RawData(x,y));    }
    TYIterator YIterator(int x,int y) const      {   return TYIterator(RawData(x,y),this->Stride());    }

    TCol Col(int x) const        {   return {*this,x};            }
    TRow Row(int y) const        {   return {*this,y};            }
};

template<typename tFmt,int pAdvance>
struct MIsView<CMView<tFmt,pAdvance>>
{
    static const bool value=true;
};

/*namespace image*/ } /*namespace buola*/ }

#endif
